package com.qihang.util;

import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.codec.binary.Base64;
/**
 * 本类是密钥工具抽象类
 * 本类实现了密钥加密，解密，实现密钥算法，密钥转换的功能
 * 
 */
public abstract class CoderUtil {

    /**
     * BASE64解密
     * 
     * @param key    已加密的字符串信息
     * @return       解密后的数据信息
     * @throws Exception
     */
	public static byte[] decryptBASE64(String key) throws Exception {
		return Base64.decodeBase64(key);
	}

	/**
     * BASE64加密
     * 
     * @param key    未加密的原始数据信息
     * @return       加密后的字符串信息
     * @throws Exception
     */
	public static String encryptBASE64(byte[] key) throws Exception {
		return Base64.encodeBase64String(key);
	}

	/**
	 * ALGORITHM 算法 <br>
	 * 可替换为以下任意一种算法，同时key值的size相应改变。
	 * 
	 * <pre>
	 * DES                  key size must be equal to 56 
	 * DESede(TripleDES)    key size must be equal to 112 or 168 
	 * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available 
	 * Blowfish             key size must be multiple of 8, and can only range from 32 to 448 (inclusive) 
	 * RC2                  key size must be between 40 and 1024 bits 
	 * RC4(ARCFOUR)         key size must be between 40 and 1024 bits
	 * </pre>
	 * 
	 * 在Key toKey(byte[] key)方法中使用下述代码
	 * <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 
	 * 替换
	 * <code> 
	 * DESKeySpec dks = new DESKeySpec(key); 
	 * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM); 
	 * SecretKey secretKey = keyFactory.generateSecret(dks); 
	 * </code>
	 * 设置密钥加密算法为"DES"静态常量
     * 
     * @since 普迅移动微门户 v2.00
	 */
	public static final String ALGORITHM = "DES";

	 /**
     * DES密钥转换<br>
     * 
     * @param key     转换前密钥
     * @return        转换后密钥
     * @throws Exception
     */
	private static Key toKey(byte[] key) throws Exception {
		DESKeySpec dks = new DESKeySpec(key);
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
		SecretKey secretKey = keyFactory.generateSecret(dks);

		// 当使用其他对称加密算法时，如AES、Blowfish等算法时，用下述代码替换上述三行代码
		// SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);

		return secretKey;
	}

	/**
     * 根据密钥生成时间对DES密钥进行解密
     * 
     * @param data    密钥最终生成时间
     * @param key     解密前字符串型密钥
     * @return        解密后的密钥信息
     * @throws Exception
     */
	public static byte[] decryptDES(byte[] data, String key) throws Exception {
		Key k = toKey(decryptBASE64(key));

		Cipher cipher = Cipher.getInstance(ALGORITHM);
		cipher.init(Cipher.DECRYPT_MODE, k);

		return cipher.doFinal(data);
	}

	 /**
     * 根据密钥生成时间对DES密钥进行加密
     * 
     * @param data    密钥最终生成时间
     * @param key     加密前的密钥
     * @return        加密后的密钥
     * @throws Exception
     */
	public static byte[] encryptDES(byte[] data, String key) throws Exception {
		Key k = toKey(decryptBASE64(key));
		Cipher cipher = Cipher.getInstance(ALGORITHM);
		cipher.init(Cipher.ENCRYPT_MODE, k);

		return cipher.doFinal(data);
	}

	/**
     * 生成密钥
     * 
     * @return        最终生成的字符串型密钥
     * @throws Exception
     */
	public static String initKey() throws Exception {
		return initKey(null);
	}

	/**
     * 根据原始信息生成密钥
     * 
     * @param seed    原始信息
     * @return        最终生成的字符串型密钥
     * @throws Exception
     */
	public static String initKey(String seed) throws Exception {
		SecureRandom secureRandom = null;

		if (seed != null) {
			secureRandom = new SecureRandom(decryptBASE64(seed));
		} else {
			secureRandom = new SecureRandom();
		}

		KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
		kg.init(secureRandom);

		SecretKey secretKey = kg.generateKey();

		return encryptBASE64(secretKey.getEncoded());
	}
}
